import base64
import uuid
import os
from django.core.files.base import ContentFile
from django.conf import settings
from rest_framework import generics, permissions, status
from rest_framework.response import Response
from .models import FaceData
from .serializers import FaceDataSerializer, FaceRegistrationSerializer
from . import services
import numpy as np

class FaceRegistrationAPI(generics.GenericAPIView):
    """
    API for registering a new face for the authenticated user.
    Expects a base64 encoded image string in the 'image' field.
    """
    permission_classes = [permissions.IsAuthenticated]
    serializer_class = FaceRegistrationSerializer

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        image_b64_string = serializer.validated_data['image']

        try:
            # Decode the base64 string
            format, imgstr = image_b64_string.split(';base64,')
            ext = format.split('/')[-1]

            # Decode base64 to binary data
            image_binary = base64.b64decode(imgstr)

            # Create temporary file path
            temp_filename = f"{request.user.username}_{uuid.uuid4()}.{ext}"
            temp_image_path = os.path.join(settings.MEDIA_ROOT, 'temp', temp_filename)

            # Ensure temp directory exists
            os.makedirs(os.path.dirname(temp_image_path), exist_ok=True)

            # Write binary data directly to file
            with open(temp_image_path, 'wb') as f:
                f.write(image_binary)

            # Verify file was created and has content
            if not os.path.exists(temp_image_path) or os.path.getsize(temp_image_path) == 0:
                return Response({'error': 'Failed to save image file.'}, status=status.HTTP_400_BAD_REQUEST)

        except Exception as e:
            import logging
            logger = logging.getLogger(__name__)
            logger.error(f"Image processing error: {e}")
            return Response({'error': 'Invalid base64 image format.'}, status=status.HTTP_400_BAD_REQUEST)

        # Extract embedding vector
        try:
            import logging
            logger = logging.getLogger(__name__)
            logger.info(f"Processing face image for user {request.user.username}, file: {temp_image_path}")

            embedding = services.represent_face(temp_image_path)

            if embedding is None:
                logger.warning(f"No face detected in image for user {request.user.username}")
                # Clean up the temporary file
                if os.path.exists(temp_image_path):
                    os.remove(temp_image_path)
                return Response({'error': 'Could not detect a face in the provided image.'}, status=status.HTTP_400_BAD_REQUEST)

            logger.info(f"Successfully extracted face embedding for user {request.user.username}")

        except Exception as e:
            import logging
            logger = logging.getLogger(__name__)
            logger.error(f"Face processing error for user {request.user.username}: {e}")

            # Clean up the temporary file
            if os.path.exists(temp_image_path):
                os.remove(temp_image_path)

            return Response({'error': f'Face processing failed: {str(e)}'}, status=status.HTTP_400_BAD_REQUEST)

        # Clean up the temporary file
        if os.path.exists(temp_image_path):
            os.remove(temp_image_path)

        # Convert numpy array to bytes for storage
        embedding_bytes = embedding.tobytes()

        # Handle face data creation/update with OneToOneField
        # Since we now use OneToOneField, we need to handle this properly
        try:
            # Try to get existing face data for this user
            face_data = FaceData.objects.get(user=request.user)
            # Update existing record
            face_data.embedding = embedding_bytes
            face_data.image_path = 'registered_via_api'
            face_data.save()
            created = False

            # Log the update
            import logging
            logger = logging.getLogger(__name__)
            logger.info(f"Updated face data for user {request.user.username}")

        except FaceData.DoesNotExist:
            # Create new face data record
            face_data = FaceData.objects.create(
                user=request.user,
                embedding=embedding_bytes,
                image_path='registered_via_api'
            )
            created = True

            # Log the creation
            import logging
            logger = logging.getLogger(__name__)
            logger.info(f"Created new face data for user {request.user.username}")

        return Response(
            FaceDataSerializer(face_data).data,
            status=status.HTTP_201_CREATED if created else status.HTTP_200_OK
        )

class UserFaceListAPI(generics.RetrieveAPIView):
    """
    API to retrieve face data for the currently authenticated user.
    Since we now use OneToOneField, each user has at most one face data record.
    """
    permission_classes = [permissions.IsAuthenticated]
    serializer_class = FaceDataSerializer

    def get_object(self):
        """
        Get the face data for the current user.
        Returns the face data object or raises Http404 if not found.
        """
        try:
            return FaceData.objects.get(user=self.request.user)
        except FaceData.DoesNotExist:
            from django.http import Http404
            raise Http404("No face data found for this user.")

    def get(self, request, *args, **kwargs):
        """
        Override get method to return a list-like response for backward compatibility.
        """
        try:
            face_data = self.get_object()
            serializer = self.get_serializer(face_data)
            # Return as a list for backward compatibility with frontend
            return Response([serializer.data])
        except:
            # Return empty list if no face data exists
            return Response([])
